package com.application;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import util.core.Equation;
import util.core.Format;
import util.exceptions.UnbalancableEquationException;
import util.exceptions.UnknownElementException;
import util.input.InputFixer;
import util.input.Parser;

public class Balance extends Activity {
    /**
     * 8FCFF3, AFFFED
     */

    boolean top;
    String reactants, products;

    private TextWatcher textChanger = new TextWatcher() {
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        public void afterTextChanged(Editable editable) {
            String text = editable.toString();
            if (text.length() != 0) {
                char last = text.charAt(text.length() - 1);
                if (!Parser.isLetter(last)) {
                    InputFixer fixer = new InputFixer(text);
                    fixer.fix1();
                    if (fixer.getResult().equals(text))
                        return;
                    if (top) {
                        ((TextView) findViewById(R.id.reactants)).setText("");
                        ((TextView) findViewById(R.id.reactants)).append(fixer.getResult());
                        System.out.println(fixer.getResult());
                    } else {
                        ((TextView) findViewById(R.id.products)).setText("");
                        ((TextView) findViewById(R.id.products)).append(fixer.getResult());
                    }
                }
            }
        }
    };
    private View.OnClickListener buttonListener = new View.OnClickListener() {
        public void onClick(View v) {
            int id = v.getId();
            if (id == R.id.balance) {
                reactants = ((EditText) findViewById(R.id.reactants)).getText().toString();
                products = ((EditText) findViewById(R.id.products)).getText().toString();
                doBalance(reactants, products);
                fixText();
            } else if (id == R.id.stoichiometry) {
                if (Equation.current != null) {
                    Intent i = new Intent(Balance.this, StoichUI.class);
                    startActivity(i);
                } else {
                    ((TextView) findViewById(R.id.result)).setText("You must type in a balanced equation.");
                }
            } else if (id == R.id.flip) {
                String a = ((EditText) findViewById(R.id.reactants)).getText().toString();
                String b = ((EditText) findViewById(R.id.products)).getText().toString();
                ((EditText) findViewById(R.id.reactants)).setText(b);
                ((EditText) findViewById(R.id.products)).setText(a);
                if (reactants != null && products != null &&
                        b.replaceAll(" ", "").equalsIgnoreCase(products.replaceAll(" ", "")) &&
                        a.replaceAll(" ", "").equalsIgnoreCase(reactants.replaceAll(" ", ""))) {
                    doBalance(b, a);
                }
            } else {
                String c;

                if (id == R.id.plus)
                    c = "+";
                else if (id == R.id.minus)
                    c = "-";
                else if (id == R.id.paren1)
                    c = "(";
                else if (id == R.id.paren2)
                    c = ")";
                else if (id == R.id.brace1)
                    c = "{";
                else
                    c = "}";
                if (top)
                    ((TextView) findViewById(R.id.reactants)).append(c);
                else
                    ((TextView) findViewById(R.id.products)).append(c);
            }

        }

        private void doBalance(String a, String b) {
            reactants = a;
            products = b;
            try {
                Equation eq = Parser.read(a + "=" + b);
                eq.balance();
                Equation.current = eq;
                ((TextView) findViewById(R.id.result)).setText(Html.fromHtml(Format.toFormattedString(eq)));
            } catch (UnbalancableEquationException e) {
                ((TextView) findViewById(R.id.result)).setText("Could not balance: " + e.getMessage());
            } catch (UnknownElementException e) {
                ((TextView) findViewById(R.id.result)).setText("Could not balance: " + e.getMessage());
            }
        }
    };

    private View.OnFocusChangeListener focusChangeListener = new View.OnFocusChangeListener() {

        public void onFocusChange(View view, boolean b) {
            fixText();

            if (view.getId() == R.id.reactants && b) {
                top = b;
            } else
                top = !b;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        top = true;
        setContentView(R.layout.balance_layout);
        findViewById(R.id.balance).setOnClickListener(buttonListener);
        findViewById(R.id.stoichiometry).setOnClickListener(buttonListener);
        findViewById(R.id.flip).setOnClickListener(buttonListener);
        findViewById(R.id.reactants).setOnFocusChangeListener(focusChangeListener);
        findViewById(R.id.products).setOnFocusChangeListener(focusChangeListener);
        ((EditText) findViewById(R.id.reactants)).addTextChangedListener(textChanger);
        ((EditText) findViewById(R.id.products)).addTextChangedListener(textChanger);

        findViewById(R.id.plus).setOnClickListener(buttonListener);
        findViewById(R.id.minus).setOnClickListener(buttonListener);
        findViewById(R.id.brace1).setOnClickListener(buttonListener);
        findViewById(R.id.brace2).setOnClickListener(buttonListener);
        findViewById(R.id.paren1).setOnClickListener(buttonListener);
        findViewById(R.id.paren2).setOnClickListener(buttonListener);

        if (Equation.current != null) {
            ((TextView) findViewById(R.id.result)).setText(Html.fromHtml(Format.toFormattedString(Equation.current)));
        }
    }

    public void fixText() {
        InputFixer fixer = new InputFixer(((TextView) findViewById(R.id.products)).getText().toString());
        fixer.fix1();
        ((TextView) findViewById(R.id.products)).setText("");
        ((TextView) findViewById(R.id.products)).append(fixer.getResult());

        fixer = new InputFixer(((TextView) findViewById(R.id.reactants)).getText().toString());
        fixer.fix1();
        ((TextView) findViewById(R.id.reactants)).setText("");
        ((TextView) findViewById(R.id.reactants)).append(fixer.getResult());
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.balance_help, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.help:
                showHelp();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showHelp() {
        Toast.makeText(getApplicationContext(), "To enter charges, use braces (ex. Al{3+} and Na{1+})." +
                "\n\nRemember to capitalize elements properly. The app will not fix " +
                "all mistakes.", Toast.LENGTH_LONG).show();
    }
}
